package com.ldy.core.web;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ldy.core.common.Constant;
import com.ldy.core.common.Result;
import com.ldy.core.entity.BaseFile;
import com.ldy.core.entity.BaseUser;
import com.ldy.core.service.BaseFileService;
import com.ldy.core.service.BaseLogsService;
import com.ldy.core.service.BaseUserService;
import com.ldy.core.util.CacheMap;
import com.ldy.core.util.Common;
import com.ldy.core.util.EncryptUtil;
import com.ldy.core.util.JwtUtil;
import com.ldy.core.util.MySession;
import com.ldy.core.util.SmsUtil;

import cn.hutool.core.codec.Base64;
/**
 * 用户登录
 */
@RestController
@RequestMapping("/user")
@CrossOrigin(allowCredentials = "true", allowedHeaders = "*")
public class UserController {
	private static final Logger logger = LoggerFactory.getLogger(UserController.class);

	@Autowired
	private BaseUserService userService;

	@Autowired
	private BaseFileService fileService;
	
	@Autowired
	private BaseLogsService logs;


	private static final CacheMap<String, String> scanCache = new CacheMap<>(5 * 60 * 1000);
	
	/**
	 * 获取 jwt token
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/jwt")
	public Result getJwt() throws Exception {
		return Result.success(JwtUtil.generateToken(MySession.get().getId()));
	}
	
	/**
	 * 自动登录
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/autoLogin")
	public Result autoLogin(String token) throws Exception {
		Assert.hasText(token,  "Token异常");
		BaseUser user = null;
		if (!token.contains(".")) {
			// token
			user = userService.selectById(token);
		} else {
			String userId = JwtUtil.verifyToken(token);
			Assert.hasText(userId, "Token异常");
			user = userService.selectById(userId);
		}
		Assert.notNull(user, "不存在的用户信息");
		String userToken = MySession.add(user);
		logs.insert("登录", user.getNickname() + "自动登录了系统");
		return Result.success().map(Constant.TOKEN_KEY, userToken) //
				.map("user", EncryptUtil.Encrypt(JSONObject.toJSONString(user), EncryptUtil.key));
	}
	
	
	/**
	 * 确定扫码登录
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/scan/confirm")
	public Result scanConfirm(String uuid) throws Exception {
		Assert.hasText(uuid, "参数异常");
		String userId = MySession.get().getId();
		scanCache.put(uuid, userId);
		logs.insert("登录","扫码登录确认");
		return Result.success();
	}
	
	/**
	 * 扫码登录
	 * TODO 
	 * 应该携带客户端信息，uuid 应该服务生成，jwt 方式，先验证是本服务签发的，在看有没确认登录，app 确认登录可以看到客户端信息
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/scan/login")
	public Result scanLogin(String uuid) throws Exception {
		Assert.hasText(uuid, "参数异常");
		String loginUserId = scanCache.get(uuid);
		if (loginUserId == null) {
			return Result.success();
		}
		BaseUser user = userService.selectById(loginUserId);
		Assert.notNull(user, "不存在的用户信息");
		String userToken = MySession.add(user);
		logs.insert("登录", user.getNickname() + "扫码登录系统");
		return Result.success().map(Constant.TOKEN_KEY, userToken) //
				.map("user", EncryptUtil.Encrypt(JSONObject.toJSONString(user), EncryptUtil.key));
	}
	
	/**
	 * 发送验证码
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/sendEcode")
	public Result sendEcode(String phone) throws Exception {
		Assert.hasText(phone, "参数异常");
		BaseUser user = userService.selectByPhone(phone);
		Assert.notNull(user, "不存在的用户信息");
		// 发送验证码
		 String number = Common.GetRandomNumber();
		 SmsUtil.cache.put(phone, number);
		SmsUtil.sendEcode(phone, number);
		return Result.success();
	}
	
	/**
	 * 短信验证登录
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/phoneLogin")
	public Result phoneLogin(String phone, String ecode) throws Exception {
		Assert.hasText(phone, "参数异常");
		Assert.hasText(ecode, "参数异常");
		String code =  SmsUtil.cache.get(phone);
		Assert.hasText(code, "验证码无效或者过期");
		Assert.isTrue(code.equals(ecode), "验证码错误");
		BaseUser user = userService.selectByPhone(phone);
		Assert.notNull(user, "不存在的用户信息");
		String userToken = MySession.add(user);
		logs.insert("登录", user.getNickname() + "验证码登录系统");
		return Result.success().map(Constant.TOKEN_KEY, userToken) //
				.map("user", EncryptUtil.Encrypt(JSONObject.toJSONString(user), EncryptUtil.key));
	}
	
	
	@PostMapping("/selectPage")
	public Result selectPage(int current, int size, String username, String nickname) {
		return Result.success(userService.selectPage(current, size, username, nickname));
	}
	
	@PostMapping("/selectList")
	public Result selectList(String orgCode) {
		QueryWrapper<BaseUser> query = new QueryWrapper<>();
		if (StringUtils.hasText(orgCode)) {
			query.like("org_code", orgCode);
		}
		return Result.success(userService.selectList(query));
	}
	

    /**
     * 图片
     *
     * @param id
     * @return
     * @throws IOException 
     */
    @GetMapping("/image")
    public void image(String id, HttpServletResponse response) throws IOException {
    	BaseFile file = fileService.getById(id);
    	if (null == file) {
    		return;
    	}
    	String content = file.getContent();
    	response.setContentType("image/png");
		OutputStream stream = response.getOutputStream();
		stream.write(Base64.decode(content.getBytes()));
		stream.flush();
		stream.close();
    }

	/**
	 * 登录
	 * 
	 * @param username
	 * @param password
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/login")
	public Result login(String username, String password) throws Exception {
		BaseUser user = userService.login(username, password);
		String token = MySession.add(user);
		logs.insert("登录", user.getNickname() + "登录了系统");
		return Result.success().map(Constant.TOKEN_KEY, token) //
				.map("user", EncryptUtil.Encrypt(JSONObject.toJSONString(user), EncryptUtil.key));
	}
	
	/**
	 * 退出
	 * 
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/logout")
	public Result logout(String token) throws Exception {
		if (StringUtils.hasText(token)) {			
			MySession.remove(token);
		}
		logs.insert("退出", "退出了系统");
		return Result.success();
	}

	/**
	 * 修改用户状态
	 * 
	 * @param id
	 * @return
	 */
	@PostMapping("/updateUserStatus")
	public Result updateUserStatus(String id) {
		userService.updateUserStatus(id);
		logs.insert("修改", "修改了用户状态");
		return Result.success();
	}

	/**
	 * 注册
	 * 
	 * @return
	 */
	@PostMapping("/register")
	public Result register(BaseUser user) {
		logger.info("UserController method: {}, params:[user: {}]", "register",
				JSONObject.toJSONString(user));
		userService.register(user);
		return Result.success(user.getId());
	}

	/**
	 * 注册
	 * 
	 * @return
	 */
	@PostMapping("/registerEcode")
	public Result register(HttpServletRequest request, BaseUser user, String ecode) {
		logger.info("UserController method: {}, params:[user: {}, ecode: {}]", "register",
				JSONObject.toJSONString(user), ecode);
		Assert.hasText(ecode, "验证码必填");
		logger.info("ecode: {}",  SmsUtil.cache.get(user.getUsername() + "_ecode"));

		Assert.isTrue(ecode.equals( SmsUtil.cache.get(user.getUsername() + "_ecode")), "验证码错误");
		userService.register(user);
		return Result.success(user.getId());
	}

	/**
	 * 找回密码
	 * 
	 * @return
	 */
	@PostMapping("/uppwd")
	public Result uppwd(HttpServletRequest request, BaseUser user, String ecode) {
		logger.info("UserController method: {}, params:[user: {}, ecode: {}]", "uppwd", JSONObject.toJSONString(user),
				ecode);
		Assert.hasText(ecode, "验证码必填");
		Assert.notNull(user, "不存在用户");
		Assert.hasText(user.getPassword(), "密码必填");
		logger.info("ecode: {}",  SmsUtil.cache.get(user.getUsername() + "_ecode"));

		Assert.isTrue(ecode.equals( SmsUtil.cache.get(user.getUsername() + "_ecode")), "验证码错误");
		BaseUser old = userService.selectByUsername(user.getUsername());
		Assert.notNull(old, "不存在用户：" + user.getUsername());
		old.setPassword(user.getPassword());
		userService.saveOrUpdate(old);
		return Result.success();
	}

	/**
	 * 休息昵称与密码
	 * 
	 * @return
	 */
	@PostMapping("/update")
	public Result update(BaseUser user) {
		logger.info("UserController method: {}, params:[user: {}]", "update", JSONObject.toJSONString(user));
		Assert.notNull(user, "不存在用户");
		Assert.hasText(user.getUsername(), "不存在用户名称");
		BaseUser old = userService.selectByUsername(user.getUsername());
		Assert.notNull(old, "不存在用户：" + user.getUsername());
		// 修改密码
		if (!StringUtils.isEmpty(user.getPassword())) {
			old.setPassword(user.getPassword());
		}
		// 修改昵称
		if (!StringUtils.isEmpty(user.getNickname())) {
			old.setNickname(user.getNickname());
		}
		// 修改角色
		if (!StringUtils.isEmpty(user.getRole())) {
			old.setRole(user.getRole());
		}
		if (!StringUtils.isEmpty(user.getPhone())) {
			old.setPhone(user.getPhone());
		}
		// 修改机构
		if (!StringUtils.isEmpty(user.getOrgCode())) {
			old.setOrgCode(user.getOrgCode());
		}
		logs.insert("修改", user.getNickname() + "修改了个人信息");
		userService.saveOrUpdate(old);
		return Result.success();
	}
	

	/**
	 * 修改密码
	 * 
	 * @return
	 */
	@PostMapping("/pwd/update")
	public Result updatePwd(String username,String oldpwd, String password) {
		logger.info("UserController method: {}, params:[username: {}]", "updatePwd", username);
		Assert.hasText(username, "不存在用户名称");
		Assert.hasText(oldpwd, "密码异常");
		Assert.hasText(password, "密码异常");
		BaseUser old = userService.selectByUsername(username);
		Assert.notNull(old, "不存在用户：" + username);
		Assert.isTrue(old.getPassword().equals(oldpwd), "密码错误");
		old.setPassword(password);
		logs.insert("修改", username + "修改了密码");
		userService.update(old);
		return Result.success();
	}
	
	/**
	 * 删除
	 * 
	 * @return
	 */
	@PostMapping("/delete")
	public Result delete(String id) {
		logger.info("method: {}, params:[id: {}]", "delete", id);
		userService.delete(id);
		return Result.success();
	}
}
